using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Windows;

namespace PrismNavigationFramework.MVVM
{
    public abstract class ViewModel<TView> : IViewModel<TView> where TView : class
    {
        public TView View { get; set; }

        public void SetView(object view)
        {
            this.View = view as TView;
            var viewAsFrameworkElement = view as FrameworkElement;
            if (viewAsFrameworkElement != null)
            {
                viewAsFrameworkElement.Loaded += (s, e) => this.OnViewLoaded();
            }
        }

        public virtual void Initialize(ViewInitializationData initializationData)
        {
            
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
        {
            if (propertyExpression.Body.NodeType == ExpressionType.MemberAccess)
            {
                var memberExpr = propertyExpression.Body as MemberExpression;

                if (memberExpr != null)
                {
                    string propertyName = memberExpr.Member.Name;

                    this.OnPropertyChanged(propertyName);
                }
                else
                {
                    throw new Exception(string.Format("Bad property supplied for INotifyPropertyChanged: {0}", propertyExpression.Name));
                }
            }
        }

        protected virtual void OnViewLoaded()
        {

        }

    }
}